/*
 * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non lorem
 * porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. Etiam sed turpis ac
 * ipsum condimentum fringilla. Maecenas magna. Proin dapibus sapien vel ante. Aliquam erat
 * volutpat. Pellentesque sagittis ligula eget metus. Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.mrd.gtimpframe.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import com.mrd.constant.PlatformConstant;
import com.mrd.gtimpframe.entity.*;
import com.mrd.gtimpframe.repository.*;
import com.mrd.gtimpframe.service.PlatformFeeService;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import com.mrd.base.Jqgrid;
import com.mrd.gtimp.business.entity.DeclarationFree;
import com.mrd.gtimp.business.repository.CommodityDao;
import com.mrd.gtimp.business.service.DeclarationFreeBiz;
import com.mrd.gtimp.order.repository.DeclaContainerDao;
import com.mrd.gtimpframe.service.ChargingService;
import com.mrd.util.CollectionUtil;
import com.mrd.util.LoginUtil;
import com.mrd.util.R;
import com.mrd.util.StringUtils;

/**
 * Created by dengdc on 2017/8/10.
 */
@Service
public class ChargingServiceImpl implements ChargingService {
  @Resource
  private GenProtocolMapper genProtocolMapper;
  @Resource
  private CompanyMapper companyMapper;
  @Resource
  private DeclarationMapper declarationMapper;
  @Resource
  private DeclarationFreeBiz declarationFreeBiz;
  @Resource
  private CommodityDao commodityDao;
  @Resource
  private DeclaContainerDao declaContainerDao;
  @Resource
  private DeclarationChargeMapper declarationChargeMapper;
  @Resource
  private GenProtocolUniteMapper genProtocolUniteMapper;
  @Resource
  private PlatformFeeService platformFeeService;

  /**
   * 根据传入参数查询报价信息
   *
   * @param params 包含报关行ID，进出口类型，直转类型，是否是通关一体化，进出口岸，申报口岸，商品项数，集装箱数
   */
  @Override
  public R queryCharging(Map<String, Object> params) {
    R result = new R();
    try {
      String supComId = params.get("supComId").toString();
      String ieType = params.get("ieType").toString();
      String transitType = params.get("transitType").toString();
      String isCCI = params.get("isCCI").toString();
      String iePortCode = params.get("iePortCode").toString();
      String declaPortCode = params.get("declaPortCode").toString();
      String contaCount = params.get("contaCount").toString();
      String goodsCount = params.get("goodsCount").toString();
      String comId = params.get("customerId").toString();
      String companyType = params.get("companyType").toString();//公司类型
      String agentSelf = params.get("agentSelf").toString();//是否委托自己

        //companyType = PlatformConstant.COM_TYPE_CUST.getKey();//公司类型
      if (StringUtils.isAnyEmpty(supComId, ieType, transitType, isCCI, iePortCode, declaPortCode,
          contaCount)) {
        result.put("msg", "参数不完整");
        result.put("result", false);
        return result;
      }

      Map<String, Object> dataMap = new HashMap<>();
      dataMap.put("supInfo", getCompanyInfo(supComId));

      Map<String,Object> dlParams = new HashMap<>();//代录单查询条件
      List<Map<String, Object>> platFormList = null;//代录单协议类别
      List<Map<String, Object>> chargingList = new ArrayList<>();// 收费清单

      if(companyType.equals(PlatformConstant.COM_TYPE_HUNHE.getKey())) {//是代录单
        if(agentSelf.equals(PlatformConstant.SELF_NO.getKey())){//是委托自己
          // 收费清单
          chargingList = getChargingList(supComId, iePortCode, "E".equals(ieType),
                  "1".endsWith(isCCI), "ZH".endsWith(transitType), goodsCount, contaCount);
        }

        dlParams.put("companyType",companyType);
        dlParams.put("agentSelf",agentSelf);
        dlParams.put("supComId",supComId);
        dlParams.put("customerId",comId);

        //不管是否都要收取代录单费用
        platFormList = getPlatFormList(goodsCount, contaCount, dlParams);
        if(chargingList!=null){
          chargingList.addAll(platFormList);
        }else{
          chargingList = platFormList;
        }
      }else{//不是代录单(只收取旧费用)
        // 收费清单
        chargingList = getChargingList(supComId, iePortCode, "E".equals(ieType),
                "1".endsWith(isCCI), "ZH".endsWith(transitType), goodsCount, contaCount);
      }

      dataMap.put("charging", chargingList);

      result.put("msg", "完成查询");
      result.put("result", true);
      result.put("data", dataMap);
      return result;
    } catch (Exception e) {
      e.printStackTrace();
      result.put("msg", "出现了未知的错误");
      result.put("result", false);
      return result;
    }
  }

  @Override
  public Page testQuery(Jqgrid jqgrid) {
    try {
      Map<String, Object> params = jqgrid.getFilterMap();
      String feeType = params.get("feeType").toString();
      String supComId = params.get("supComId").toString();
      String ieType = params.get("ieType").toString();
      String transitType = params.get("transitType").toString();
      String isCCI = params.get("isCCI").toString();
      String iePortCode = params.get("iePortCode").toString();
      String contaCount = params.get("contaCount").toString();
      String goodsCount = params.get("goodsCount").toString();
      if (StringUtils.isAnyEmpty(supComId, ieType, transitType, isCCI, iePortCode, feeType,
          contaCount)) {
        return null;
      }
      List<Map<String, Object>> list;
      if ("0".equals(feeType)) {
        list = getChargingList(supComId, iePortCode, "E".equals(ieType), "1".endsWith(isCCI),
            "ZH".endsWith(transitType), goodsCount, contaCount);
      } else {
        list = getCostList(supComId, iePortCode, "E".equals(ieType), "1".endsWith(isCCI),
            "ZH".endsWith(transitType), goodsCount, contaCount);
      }

      return new PageImpl(list, new PageRequest(0, 100), list.size());
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 获取收费清单
   *
   * @param supComId 申报报关行ID
   * @param portCode 进出口口岸代码
   * @param isExport 是否是进口
   * @param isCCI 是否是通关一体化
   * @param isDirect 是否是直航
   * @param goodsCount 商品项数
   * @param contaCount 柜量
   */
  public List<Map<String, Object>> getChargingList(String supComId, String portCode,
      boolean isExport, boolean isCCI, boolean isDirect, String goodsCount, String contaCount) {
    List<GenProtocol> calcProtocols = collectProtocols(supComId, portCode, isCCI);
    List<Map<String, Object>> chargingList = new ArrayList<>();
    for (GenProtocol calcProtocol : calcProtocols) {
      if (isSuitableProtocol(calcProtocol.getProps(), isExport, isDirect)) {
        Map<String, Object> chargingMap = countChargingFee(calcProtocol.getFees(),
            calcProtocol.getProps(), contaCount, goodsCount);
        if (chargingMap.size() != 0) {
          chargingMap.put("name", calcProtocol.getName());
          chargingMap.put("descript", calcProtocol.getDescript());
          chargingList.add(chargingMap);
        }
      }
    }
    return chargingList;
  }

  /**
   * 出口口岸 代垫费收取
   */
  private List<GenProtocol> secondSupplierFeeAdvance(String portCode) {
    List<GenProtocol> protocols = new ArrayList<>();
    if (StringUtils.isNotEmpty(portCode)) {
      List<GenProtocol> secondSupProtocols =
          genProtocolMapper.selectByPortCodeAndStatus(portCode, GenProtocol.EFFECTIVE);
      for (GenProtocol protocol : secondSupProtocols) {
        if ((!isCCIProtocol(protocol) && isAdvanceFeeProtocol(protocol))
            || isProtocolFitAll(protocol)) {
          protocols.add(protocol);
        }
      }
    }
    return protocols;
  }

  /**
   * 获取成本清单
   *
   * @param supComId 申报报关行ID
   * @param portCode 进出口口岸代码
   * @param isExport 是否是出口
   * @param isCCI 是否是通关一体化
   * @param isDirect 是否是直航
   * @param goodsCount 商品项数
   * @param contaCount 柜量
   */
  private List<Map<String, Object>> getCostList(String supComId, String portCode, boolean isExport,
      boolean isCCI, boolean isDirect, String goodsCount, String contaCount) {
    List<GenProtocol> calcProtocols = collectProtocols(supComId, portCode, isCCI);

    List<Map<String, Object>> costList = new ArrayList<>();
    for (GenProtocol calcProtocol : calcProtocols) {
      if (isSuitableProtocol(calcProtocol.getProps(), isExport, isDirect)) {
        Map<String, Object> costMap =
            countCostFee(calcProtocol.getFees(), calcProtocol.getProps(), contaCount, goodsCount);
        if (costMap.size() != 0) {
          costMap.put("name", calcProtocol.getName());
          costMap.put("descript", calcProtocol.getDescript());
          costMap.put("chargeType","1");
          if (!isCCIProtocol(calcProtocol)) {
            costMap.put("supplierId", calcProtocol.getSupplierId());
          }
          costList.add(costMap);
        }
      }
    }
    return costList;
  }

  /**
   * 收集用于计费的协议
   *
   * @param supComId 申报报关行ID
   * @param portCode 进出口口岸代码
   * @param isCCI 是否是通关一体化
   */
  public List<GenProtocol> collectProtocols(String supComId, String portCode, boolean isCCI) {
    List<GenProtocol> calcProtocols = new ArrayList<>();
    // 查询有效协议
    GenProtocolUnite unite =
        genProtocolUniteMapper.selectBySupplierIdAndStatusIsEffective(supComId);
    if (unite == null) {
      return new ArrayList<>();
    }
    List<GenProtocol> protocols = selectByUniteId(unite.getId());
    if (protocols == null) {
      protocols = genProtocolMapper.selectByUniteId(unite.getId());
    }
    if (isCCI) {
      // 收集代理费\优惠费
      for (GenProtocol protocol : protocols) {
        if (isAdvanceFeeProtocol(protocol)) {
          continue;
        }
        if (isProtocolFitAll(protocol) || isCCIProtocol(protocol)) {
          calcProtocols.add(protocol);
        }
      }
      // 收集代垫费
      calcProtocols.addAll(secondSupplierFeeAdvance(portCode));
    } else {
      // 收集代理费\优惠费
      for (GenProtocol protocol : protocols) {
        if (!isCCIProtocol(protocol) && !isAdvanceFeeProtocol(protocol)) {
          calcProtocols.add(protocol);
        }
      }
      // 收集代垫费
      for (GenProtocol protocol : protocols) {
        if (!isCCIProtocol(protocol) && isAdvanceFeeProtocol(protocol)) {
          calcProtocols.add(protocol);
        }
      }
    }
    return calcProtocols;
  }

  @Cacheable(value = "protocolCache", key = "#id + '_protocol'")
  public List<GenProtocol> selectByUniteId(String id) {
    List<GenProtocol> protocols = genProtocolMapper.selectByUniteId(id);
    return protocols;
  }


  /**
   * 计算并保存报关单费用
   *
   * @param declarationId 报关单ID
   */
  @Transactional
  public Object[] calcDeclarationFee(String declarationId) {
    Declaration declaration = declarationMapper.selectByPrimaryKey(declarationId);
    String goodsCount = String.valueOf(commodityDao.countByDeclarationId(declarationId));
    String contaCount = String.valueOf(declaContainerDao.countByDeclarationId(declarationId));
    boolean isExport = "E".equals(declaration.getDeclarationType());
    boolean isCCI = "1".equals(declaration.getIsTongguanYth());
    boolean isZH = "直航".endsWith(declaration.getDataType());
    String iePortCode = declaration.getExportPortCode();
    String supId = declaration.getSupId();
    String supCustomCode = companyMapper.selectByPrimaryKey(supId).getComCustomsCode();
    String enterType = PlatformConstant.COM_TYPE_CUST.getKey();
    String comId = declaration.getCustomerComId();//下单客户ID
    String comCustomCode = companyMapper.selectByPrimaryKey(comId).getComCustomsCode();
    String agentSelf = PlatformConstant.SELF_NO.getKey();//是否委托自己

    if(StringUtils.isNotEmpty(declaration.getEnterType())){
        if(declaration.getEnterType().equals("1")){
            enterType = PlatformConstant.COM_TYPE_HUNHE.getKey();
        }
    }
    //判断是否委托自己
    if(StringUtils.isNoneEmpty(comCustomCode,supCustomCode)&& comCustomCode.equals(supCustomCode)){
      agentSelf = PlatformConstant.SELF_YES.getKey();
    }

    Map<String,Object> dlParams = new HashMap<>();//代录单查询条件
    List<Map<String, Object>> platFormList = null;//代录单协议类别
    List<Map<String, Object>> chargingList = new ArrayList<>();// 收费清单
    List<Map<String, Object>> costList = new ArrayList<>();// 成本清单

    if(enterType.equals(PlatformConstant.COM_TYPE_HUNHE.getKey())) {//是代录单
      if(agentSelf.equals(PlatformConstant.SELF_NO.getKey())){//是委托自己
        // 收费清单
        chargingList =
                getChargingList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
        // 成本清单
        costList =
                getCostList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
      }

      dlParams.put("companyType",enterType);
      dlParams.put("agentSelf",agentSelf);
      dlParams.put("supComId",supId);
      dlParams.put("customerId",comId);

      //不管是否都要收取代录单费用
      platFormList = getPlatFormList(goodsCount, contaCount, dlParams);
      if(chargingList!=null){
        chargingList.addAll(platFormList);
      }else{
        chargingList = platFormList;
      }
        /**把代录入费用累加到费用列表**/
        if(costList!=null) {
            List<Map<String, Object>> platFeeCountList = getPlatFormCoustList(dlParams);
            if(costList==null){
                costList = platFeeCountList;
            }else{
                costList.addAll(platFeeCountList);
            }
        }
    }else{//不是代录单(只收取旧费用)
      // 收费清单
      chargingList =
              getChargingList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
      // 成本清单
      costList =
              getCostList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
    }
    double totalFee = 0d;
    for (Map<String, Object> map : chargingList) {
      totalFee += (double) map.get("totalPrice");
    }
    if (totalFee < 0) {
      totalFee = 0d;
    }
    String stringTotalFee = String.valueOf(totalFee);
    DeclarationFree declarationFree =
        declarationFreeBiz.saveFeeWithUnitAndSumFee(declarationId, stringTotalFee, stringTotalFee);

    declarationChargeMapper.deleteByDid(declarationId);
    saveChargeRecords(declarationId, supId, chargingList, true);
    saveChargeRecords(declarationId, null, costList, false);
    return new Object[] {declarationFree.getPay_id(), chargingList, totalFee};
  }

  /**
   * 计算多份报关单费用
   */
  @Transactional
  @Override
  public Object[] calcDeclarationFee(String[] declarationIds) throws Exception {
    if (ArrayUtils.isEmpty(declarationIds)) {
      return null;
    }
    List<Declaration> declarations =
        declarationMapper.selectByPrimaryKeyList(Arrays.asList(declarationIds));
    Map<String, String> feeMap = new HashMap<>();
    double allTotalFee = 0d;
    List<com.mrd.gtimp.business.entity.Declaration> oDeclarationList = new ArrayList<>(); // 报关单集合，jpa版本
    for (Declaration declaration : declarations) {
      String declarationId = declaration.getId();
      String goodsCount = String.valueOf(commodityDao.countByDeclarationId(declarationId));
      String contaCount = String.valueOf(declaContainerDao.countByDeclarationId(declarationId));
      boolean isExport = "E".equals(declaration.getDeclarationType());
      boolean isCCI = "1".equals(declaration.getIsTongguanYth());
      boolean isZH = "直航".endsWith(declaration.getDataType());
      String iePortCode = declaration.getExportPortCode();
      String supId = declaration.getSupId();
      String enterType = PlatformConstant.COM_TYPE_CUST.getKey();//代录单
      String comId = declaration.getCustomerComId();//下单客户ID
      String agentSelf = PlatformConstant.SELF_NO.getKey();//是否委托自己
      String supCustomCode = companyMapper.selectByPrimaryKey(supId).getComCustomsCode();
      String comCustomCode = companyMapper.selectByPrimaryKey(comId).getComCustomsCode();
      //判断是否委托自己
      if(StringUtils.isNoneEmpty(supCustomCode,comCustomCode)&& comCustomCode.equals(supCustomCode)){
        agentSelf = PlatformConstant.SELF_YES.getKey();
      }
      //代录单费用计算(han)
      if(StringUtils.isNotEmpty(declaration.getEnterType())){
        if(declaration.getEnterType().equals("1")){
          enterType = PlatformConstant.COM_TYPE_HUNHE.getKey();
        }
      }
      Map<String,Object> dlParams = new HashMap<>();//代录单查询条件
      List<Map<String, Object>> platFormList = null;//代录单协议类别
      List<Map<String, Object>> chargingList = new ArrayList<>();// 收费清单
      List<Map<String, Object>> costList = new ArrayList<>();// 成本清单

      if(enterType.equals(PlatformConstant.COM_TYPE_HUNHE.getKey())) {//是代录单
        if(agentSelf.equals(PlatformConstant.SELF_NO.getKey())){//是委托自己
          // 收费清单
          chargingList =
                  getChargingList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
          // 成本清单
          costList =
                  getCostList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
        }

        dlParams.put("companyType",enterType);
        dlParams.put("agentSelf",agentSelf);
        dlParams.put("supComId",supId);
        dlParams.put("customerId",comId);

        //不管是否都要收取代录单费用
        platFormList = getPlatFormList(goodsCount, contaCount, dlParams);
        if(chargingList!=null){
          chargingList.addAll(platFormList);
        }else{
          chargingList = platFormList;
        }
          /**把代录入费用累加到费用列表**/
          if(costList!=null) {
              List<Map<String, Object>> platFeeCountList = getPlatFormCoustList(dlParams);
              if(costList==null){
                  costList = platFeeCountList;
              }else{
                  costList.addAll(platFeeCountList);
              }
          }

      }else{//不是代录单(只收取旧费用)
        // 收费清单
        chargingList =
                getChargingList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
        // 成本清单
        costList =
                getCostList(supId, iePortCode, isExport, isCCI, isZH, goodsCount, contaCount);
      }

      if(CollectionUtil.isEmpty(chargingList)){
         throw new Exception("报关单未找到相应计费条件");
      }
      double totalFee = 0d;
      for (Map<String, Object> map : chargingList) {
        totalFee += (double) map.get("totalPrice");

      }
      allTotalFee += totalFee; // 计算总费用

      declarationChargeMapper.deleteByDid(declarationId);
      saveChargeRecords(declarationId, supId, chargingList, true);
      saveChargeRecords(declarationId, null, costList, false);

      // 收集每票单的总费用，用于插入declarationFree
      feeMap.put(declarationId, String.valueOf(totalFee));

      com.mrd.gtimp.business.entity.Declaration od =
          new com.mrd.gtimp.business.entity.Declaration();
      od.setId(declarationId);
      od.setDeclaration_free(totalFee);
      od.setBusinessId(declaration.getBusinessId());
      oDeclarationList.add(od);
    }

    // 组装数据，用于页面展示
    Map<String, String[]> classifyFeeMap = new HashMap<>();
    String stringAllTotalFee = String.valueOf(allTotalFee);
    for (String declarationId : feeMap.keySet()) {
      String singleFee = feeMap.get(declarationId);
      classifyFeeMap.put(declarationId, new String[] {singleFee, stringAllTotalFee});
    }

    // 保存报关单计费信息
    String payId = declarationFreeBiz.getPayId();
    declarationFreeBiz.saveFeeWithCommonPayId(payId, classifyFeeMap);

    return new Object[] {payId, stringAllTotalFee, oDeclarationList};
  }

  @Override
  @Transactional
  public void customerDidPay(String declarationId) {
    String customerComId = LoginUtil.getLoginUser().getCompany().getId();
    declarationChargeMapper.updateByDidAndChargeComIdAndInoutWithStatus(declarationId,
        customerComId, "0", "1");

  }

  @Override
  public void customerDidPay(List<String> declarationIdList) {
    String customerComId = LoginUtil.getLoginUser().getCompany().getId();
    declarationChargeMapper.batchUpdateByDidAndChargeComIdAndInoutWithStatus(declarationIdList,
        customerComId, "0", "1");
  }

  @Override
  @Transactional
  public  void saveChargeRecords(String declarationId, String comId,
      List<Map<String, Object>> feeList, boolean isIncome) {
    List<DeclarationCharge> charges = new ArrayList<>();
    for (Map<String, Object> map : feeList) {
      DeclarationCharge charge = new DeclarationCharge();
      Object feeName = map.get("name");
      Object unitPrice = map.get("unitPrice");
      Object count = map.get("count");
      Object totalPrice = map.get("totalPrice");
      Object descript = map.get("descript");
      Object protocolId = map.get("protocolId");
      Object supplierId = map.get("supplierId");
      Object chargeType = map.get("chargeType");

      charge.setId(StringUtils.getUUID());
      charge.setChargeComId(supplierId == null ? comId : supplierId.toString());
      charge.setProtocolId(protocolId == null ? null : protocolId.toString());
      charge.setDid(declarationId);
      charge.setFeeName(feeName == null ? null : feeName.toString());
      charge.setUnitPrice(unitPrice == null ? null : BigDecimal.valueOf((double) unitPrice));
      charge.setCount(count == null ? null : BigDecimal.valueOf((double) count));
      charge.setTotalFee(totalPrice == null ? null : BigDecimal.valueOf((double) totalPrice));
      charge.setDescript(descript == null ? null : descript.toString());
      charge.setInOut(isIncome ? "0" : "1");
      charge.setCreateTime(new Date());
      charge.setCreator("SYSTEM");
      charge.setStatus("0");
      charge.setChargeType(chargeType == null ? null : chargeType.toString());

      charges.add(charge);
    }
    if(charges!=null && charges.size()>0)
      declarationChargeMapper.batchInsert(charges);
  }

  /**
   * 是否是可以用于计算费用报价协议
   *
   * @param props 报价协议属性
   * @param isExport 出口 false 进口， true 出口
   * @param isDirect 是直航， true 直航， false 转关
   */
  private boolean isSuitableProtocol(List<GenProtocolProp> props, boolean isExport,
      boolean isDirect) {
    boolean result = true;
    for (GenProtocolProp prop : props) {
      if (StringUtils.isEmpty(prop.getPropDtCode())) {
        return false;
      }
      switch (prop.getPropDtCode()) {
        case "imp":
          result &= !isExport;
          break;
        case "exp":
          result &= isExport;
          break;
        case "direct":
          result &= isDirect;
          break;
        case "transit":
          result &= !isDirect;
          break;
        case "fee_offer":
          result &= true;
          break;
        default:
      }
    }
    return result;
  }

  /**
   * 是通关一体化协议-包含线上和线下
   *
   * @param protocol 报价协议
   */
  private boolean isCCIProtocol(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      String dtCode = prop.getPropDtCode();
      if ("protocol_biz_cci".equals(dtCode) || "protocol_biz_cci_online".equals(dtCode)
          || "protocol_biz_cci_offline".equals(dtCode)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 是适用全部业务类型的协议
   *
   * @param protocol 报价协议
   */
  private boolean isProtocolFitAll(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      if ("protocol_biz_all".equals(prop.getPropDtCode())) {
        return true;
      }
    }
    return false;
  }

  /**
   * 是线上通关一体化协议
   *
   * @param protocol 报价协议
   */
  private boolean isOnlineCCIProtocol(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      if ("protocol_biz_cci_online".equals(prop.getPropDtCode())) {
        return true;
      }
    }
    return false;
  }

  /**
   * 是线下通关一体化协议
   *
   * @param protocol 报价协议
   */
  private boolean isOfflineCCIProtocol(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      if ("protocol_biz_cci_offline".equals(prop.getPropDtCode())) {
        return true;
      }
    }
    return false;
  }

  /**
   * 是代垫费协议
   *
   * @param protocol 报价协议
   */
  private boolean isAdvanceFeeProtocol(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      if ("fee_advance".equals(prop.getPropDtCode())) {
        return true;
      }
    }
    return false;
  }

  /**
   * 是费用类型
   *
   * @param protocol 报价协议
   */
  private boolean isFeeOffer(GenProtocol protocol) {
    for (GenProtocolProp prop : protocol.getProps()) {
      if ("fee_offer".equals(prop.getPropDtCode())) {
        return true;
      }
    }
    return false;
  }

  /**
   * 计算费用 按照不同的计算规则进行
   *
   * @param fees 费用信息 包含报价和成本
   * @param props 报价属性
   * @param contaCount 集装箱数量
   * @param goodsCount 商品数量
   */
  private Map<String, Object> countChargingFee(List<GenProtocolFee> fees,
      List<GenProtocolProp> props, String contaCount, String goodsCount) {
    Map<String, Object> feeMap = new HashMap<>();
    out: for (GenProtocolProp prop : props) {
      for (GenProtocolFee fee : fees) {
        if ("1".equals(fee.getIeType())) { // 成本费用在计价范围内
          continue;
        }
        feeMap = getFeeMap(contaCount, goodsCount, prop, fee);
        if (feeMap.size() > 0) {
          break out;
        }
      }
    }
    return feeMap;
  }


  /**
   * 计算费用 按照不同的计算规则进行
   *
   * @param fees 费用信息 包含报价和成本
   * @param props 报价属性
   * @param contaCount 集装箱数量
   * @param goodsCount 商品数量
   */
  private Map<String, Object> countCostFee(List<GenProtocolFee> fees, List<GenProtocolProp> props,
      String contaCount, String goodsCount) {
    Map<String, Object> feeMap = new HashMap<>();
    out: for (GenProtocolProp prop : props) {
      for (GenProtocolFee fee : fees) {
        if ("0".equals(fee.getIeType())) { // 成本费用在计价范围内
          continue;
        }
        feeMap = getFeeMap(contaCount, goodsCount, prop, fee);
        if (feeMap.size() > 0) {
          break out;
        }
      }
    }
    return feeMap;
  }

  private Map<String, Object> getFeeMap(String contaCount, String goodsCount, GenProtocolProp prop,
      GenProtocolFee fee) {
    Map<String, Object> feeMap = new HashMap<>();
    // 列出所有用于计算的数据
    // 起步价
    // BigDecimal startPrice = fee.getStartPrice();
    // startPrice = startPrice == null ? BigDecimal.valueOf(0) : startPrice;
    // double startPriceD = startPrice.doubleValue();
    // 起算数量
    BigDecimal startCount = fee.getStartCount();
    startCount = startCount == null ? BigDecimal.valueOf(0) : startCount;
    int startCountI = startCount.intValue();
    // 单价
    BigDecimal unitPrice = fee.getUnitPrice();
    unitPrice = unitPrice == null ? BigDecimal.valueOf(0) : unitPrice;
    double unitPriceD = unitPrice.doubleValue();
    // 封顶价
    BigDecimal capPrice = fee.getCapPrice();
    capPrice = capPrice == null ? BigDecimal.valueOf(0) : capPrice;
    double capPriceD = capPrice.doubleValue();
    // 商品项数
    Integer gc = StringUtils.isEmpty(goodsCount) ? 0 : Integer.valueOf(goodsCount);
    // 集装箱数
    Integer cc = StringUtils.isEmpty(contaCount) ? 0 : Integer.valueOf(contaCount);
    // 一页八项商品
    int pageSize = 8;

    /*
     * 往下开始计算费用
     */
    double actUnitPrice = unitPriceD;
    double actTotal = 0;
    double actCount = 0;

    /*
     * 按票计费 实际收费单价 = 起步价 + 单价 实际总费用 = 实际收费单价
     */
    if ("count_by_part".equals(prop.getPropDtCode())) {
      // actUnitPrice = startPriceD + unitPriceD;
      actUnitPrice = unitPriceD;
      actTotal = actUnitPrice;
      actCount = 1;
    }

    /*
     * 按页计费 按照传入的商品项数计算需要的页数 实际收费单价 = 单价 总费用 = (起步价 + 收费页数 + 实际收费单价) 实际总费用 = 总费用 > 封顶价 ? 封顶价 : 总费用
     */
    if ("count_by_page".equals(prop.getPropDtCode())) {
      int pages = gc / pageSize;
      pages = pages + (gc % pageSize > 0 ? 1 : 0);
      int countPage = pages - startCountI + 1;
      actUnitPrice = unitPriceD;
      actTotal = 0;
      if (countPage > 0) {
        // actTotal = startPrice.doubleValue() + countPage * actUnitPrice;
        actTotal = countPage * actUnitPrice;
      }
      actCount = countPage;
    }

    /*
     * 按柜计费 按照传入的商品项数计算需要的柜数 实际收费单价 = 单价 总费用 = (起步价 + 收费页数 + 实际收费单价) 实际总费用 = 总费用 > 封顶价 ? 封顶价 : 总费用
     */
    if ("count_by_conta".equals(prop.getPropDtCode())) {
      int countConta = cc - startCountI + 1;
      if (countConta < 0) {
        countConta = 0;
      }
      actUnitPrice = unitPriceD;
      actTotal = 0;
      if (countConta > 0) {
        // actTotal = startPriceD + countConta * actUnitPrice;
        actTotal = countConta * actUnitPrice;
      }
      actCount = countConta;
    }

    if (actTotal * capPriceD > 0 && Math.abs(actTotal) > Math.abs(capPriceD)) {
      actTotal = capPriceD;
    }
    /*
     * 总费不为0时纳入计算
     */
    if (actTotal != 0) {
      feeMap.put("count", actCount);
      feeMap.put("unitPrice", actUnitPrice);
      feeMap.put("totalPrice", actTotal);
      feeMap.put("protocolId", prop.getProtocolId());
    }
    return feeMap;
  }

  /**
   * 获取公司信息
   *
   * @param comId 公司ID
   */
  private Map<String, Object> getCompanyInfo(String comId) {
    Map<String, Object> infoMap = new HashMap<>();
    Company company = companyMapper.selectByPrimaryKey(comId);
    infoMap.put("comName", company.getComName());
    infoMap.put("comCode", company.getComCustomsCode());
    infoMap.put("contactor", company.getComContactor());
    infoMap.put("tel", company.getComPhone());
    infoMap.put("phone", company.getComMobile());
    return infoMap;
  }

    /**
     * 代录单计费
     * @param goodsCount
     * @param contaCount
     * @param params
     * @return
     */
  public List<Map<String, Object>> getPlatFormList(String goodsCount, String contaCount,Map<String, Object> params) {
      List<PlatformFee> platformFeeList = platformFeeService.queryPlatformFeePay(params);
      List<Map<String, Object>> rtnList = new ArrayList<>();
      for (PlatformFee platformFee : platformFeeList) {
              Map<String, Object> feeMap = new HashMap<>();
              // 列出所有用于计算的数据
              // 起算数量
              int startCountI = 0;
              // 单价
              BigDecimal unitPrice = platformFee.getFeeAmount();
              unitPrice = unitPrice == null ? BigDecimal.valueOf(0) : unitPrice;
              double unitPriceD = unitPrice.doubleValue();

              // 商品项数
              Integer gc = StringUtils.isEmpty(goodsCount) ? 0 : Integer.valueOf(goodsCount);
              // 集装箱数
              Integer cc = StringUtils.isEmpty(contaCount) ? 0 : Integer.valueOf(contaCount);
              // 一页八项商品
              int pageSize = 8;

              /*
               * 往下开始计算费用
               */
              double actUnitPrice = unitPriceD;
              double actTotal = 0;
              double actCount = 0;

              /*
               * 按票计费 实际收费单价 = 起步价 + 单价 实际总费用 = 实际收费单价
               */
              if ("count_by_part".equals(platformFee.getChargeMode())) {
                  // actUnitPrice = startPriceD + unitPriceD;
                  actUnitPrice = unitPriceD;
                  actTotal = actUnitPrice;
                  actCount = 1;
              }

              /*
               * 按页计费 按照传入的商品项数计算需要的页数 实际收费单价 = 单价 总费用 = (起步价 + 收费页数 + 实际收费单价) 实际总费用 = 总费用 > 封顶价 ? 封顶价 : 总费用
               */
              if ("count_by_page".equals(platformFee.getChargeMode())) {
                  int pages = gc / pageSize;
                  pages = pages + (gc % pageSize > 0 ? 1 : 0);
                  int countPage = pages - startCountI + 1;
                  actUnitPrice = unitPriceD;
                  actTotal = 0;
                  if (countPage > 0) {
                      // actTotal = startPrice.doubleValue() + countPage * actUnitPrice;
                      actTotal = countPage * actUnitPrice;
                  }
                  actCount = countPage;
              }

              /*
               * 按柜计费 按照传入的商品项数计算需要的柜数 实际收费单价 = 单价 总费用 = (起步价 + 收费页数 + 实际收费单价) 实际总费用 = 总费用 > 封顶价 ? 封顶价 : 总费用
               */
              if ("count_by_conta".equals(platformFee.getChargeMode())) {
                  int countConta = cc - startCountI + 1;
                  if (countConta < 0) {
                      countConta = 0;
                  }
                  actUnitPrice = unitPriceD;
                  actTotal = 0;
                  if (countConta > 0) {
                      // actTotal = startPriceD + countConta * actUnitPrice;
                      actTotal = countConta * actUnitPrice;
                  }
                  actCount = countConta;
              }

              /*
               * 总费不为0时纳入计算
               */
              if (actTotal != 0) {
                  feeMap.put("count", actCount);
                  feeMap.put("unitPrice", actUnitPrice);
                  feeMap.put("totalPrice", actTotal);
                  feeMap.put("protocolId", platformFee.getId());
              }
              if (feeMap.size() != 0) {
                  feeMap.put("name", platformFee.getFeeName());
                  feeMap.put("descript", platformFee.getFeeName());
                  rtnList.add(feeMap);
              }
      }
      return rtnList;
  }

  /**
   * 查询代录单费用项列表
   * @author han
   * @param params
   * @return
   */
  public List<Map<String, Object>> getPlatFormCoustList(Map<String, Object> params) {
    List<PlatformFee> platformFeeCountList = platformFeeService.queryPlatformFeePay(params);
    List<Map<String, Object>> rtnList = new ArrayList<>();
    if(platformFeeCountList!=null && platformFeeCountList.size()>0){
      for(PlatformFee platformFee : platformFeeCountList){
          Map<String,Object> feeMap = new HashMap<>();
          feeMap.put("count", new Double(1.0));
          feeMap.put("unitPrice", platformFee.getFeeAmount().doubleValue());
          feeMap.put("totalPrice", platformFee.getFeeAmount().doubleValue());
          feeMap.put("protocolId", platformFee.getId());
          feeMap.put("name", platformFee.getFeeName());
          feeMap.put("descript", platformFee.getFeeName());
          feeMap.put("chargeType","2");
          rtnList.add(feeMap);
      }
    }
    return rtnList;
  }
}
